<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>游戏大厅</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css">
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="./css/game_hall.css">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        secondary: '#FF7D00',
                        neutral: '#1D2129',
                        'iron': '#858D96',
                        'bronze': '#CD7F32',
                        'silver': '#C0C0C0',
                        'gold': '#FFD700',
                        'platinum': '#E5E4E2',
                        'diamond': '#B9F2FF',
                        '超凡': '#FF00FF',
                        '神话': '#FF4500',
                        '赋能': '#00FF00',
                    },
                    fontFamily: {
                        sans: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .shutdown-button {
                @apply bg-red-600 hover:bg-red-700 text-white font-medium py-2 px-4 rounded-lg transition-all duration-300 transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-red-500/50 flex items-center z-50;
            }
    
            /* 小屏幕设备调整 */
        @screen sm {
            .shutdown-button {
                @apply right-2 py-1 px-3 text-sm;
                }
        }
            .content-auto {
                content-visibility: auto;
            }
            .rank-card {
                @apply rounded-xl p-6 shadow-lg transition-all duration-300;
            }
            .rank-icon {
                @apply text-4xl mr-2;
            }
            .stats-grid {
                @apply grid grid-cols-1 md:grid-cols-3 gap-4 mt-4;
            }
            .stat-card {
                @apply bg-neutral/50 rounded-lg p-3 text-center;
            }
            .match-btn {
                @apply bg-primary hover:bg-primary/80 text-white font-bold py-3 px-8 rounded-full text-lg shadow-lg transition-all duration-300 transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-primary/50 flex items-center justify-center mx-auto;
            }
            .matching-btn {
                @apply bg-red-500 hover:bg-red-600 text-white font-bold py-3 px-8 rounded-full text-lg shadow-lg transition-all duration-300 transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-red-400/50 flex items-center justify-center mx-auto;
            }
            .unranked-badge {
                @apply bg-gray-600 text-white rounded-full px-4 py-2 text-center inline-block;
            }
            .online-user-list {
                @apply fixed right-0 top-0 h-full bg-neutral/90 backdrop-blur-md shadow-2xl w-64 border-l border-gray-700 overflow-y-auto z-40 flex flex-col;
            }
            .user-item {
                @apply flex items-center p-3 hover:bg-gray-800 transition-colors;
            }
            .user-avatar {
                @apply w-10 h-10 rounded-full bg-gray-700 flex items-center justify-center overflow-hidden mr-3 relative;
            }
            .status-dot {
                @apply w-3 h-3 rounded-full absolute bottom-0 right-0 border-2 border-neutral;
            }
            .section-header {
                @apply text-xs font-semibold text-gray-400 uppercase tracking-wider px-3 py-2 bg-gray-800;
            }
            .search-box {
                @apply p-3 border-t border-gray-700;
            }
            .search-input {
                @apply w-full bg-gray-800 border border-gray-700 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-primary focus:border-transparent;
            }
            .search-button {
                @apply mt-2 w-full bg-primary hover:bg-primary/80 text-white font-medium py-2 px-4 rounded-lg transition-colors;
            }
            .friends-scroll-container {
                @apply flex-1 overflow-y-auto;
            }
                    @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
        
        :root {
            --sidebar-width: 16rem; /* 64 */
        }
        
        body {
            font-family: 'Inter', 'system-ui', sans-serif;
            background: linear-gradient(135deg, #1a202c 0%, #2d3748 100%);
        }
        
        .split-input-container {
            display: grid;
            grid-template-columns: 1fr auto 1fr;
            gap: 0.5rem;
            align-items: center;
        }
        
        .split-input {
            width: 100%;
            background-color: rgba(31, 41, 55, 0.8);
            border: 1px solid rgba(55, 65, 81, 0.7);
            border-radius: 0.5rem;
            padding: 0.625rem 0.75rem;
            font-size: 0.875rem;
            color: white;
            transition: all 0.2s ease;
        }
        
        .split-input:focus {
            outline: none;
            border-color: #3b82f6;
            box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
        }
        
        .split-divider {
            color: #9ca3af;
            font-weight: bold;
            padding: 0 0.25rem;
            user-select: none;
        }
        
        .search-button {
            background-color: #165DFF;
            color: white;
            font-weight: 500;
            padding: 0.5rem 1rem;
            border-radius: 0.5rem;
            width: 100%;
            transition: background-color 0.2s ease;
            margin-top: 0.75rem;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .search-button:hover {
            background-color: #0e4cd9;
        }
        
        .online-user-list {
            width: var(--sidebar-width);
            position: fixed;
            right: 0;
            top: 0;
            height: 100vh;
            background: rgba(29, 33, 41, 0.9);
            backdrop-filter: blur(12px);
            box-shadow: -4px 0 15px rgba(0, 0, 0, 0.3);
            border-left: 1px solid rgba(55, 65, 81, 0.7);
            overflow-y: auto;
            z-index: 40;
            display: flex;
            flex-direction: column;
        }
        
        .user-item {
            display: flex;
            align-items: center;
            padding: 0.75rem;
            transition: background-color 0.2s;
            cursor: pointer;
        }
        
        .user-item:hover {
            background-color: rgba(55, 65, 81, 0.5);
        }
        
        .section-header {
            font-size: 0.75rem;
            font-weight: 600;
            color: #9ca3af;
            text-transform: uppercase;
            letter-spacing: 0.05em;
            padding: 0.5rem 0.75rem;
            background-color: rgba(31, 41, 55, 0.7);
        }
        
        .search-box {
            padding: 0.75rem;
            border-top: 1px solid rgba(55, 65, 81, 0.7);
            background-color: rgba(29, 33, 41, 0.8);
        }
        
        /* 其他样式保持不变 */
        .friends-scroll-container {
            flex: 1;
            overflow-y: auto;
        }
        }
    </style>
</head>

<body class="bg-gradient-to-br from-gray-900 to-gray-800 min-h-screen text-white font-sans">
    <!-- 在线用户列表侧边栏 -->
    <div class="online-user-list">
        <div class="p-4 border-b border-gray-700">
            <h3 class="text-lg font-bold flex items-center">
                <i class="fa fa-users mr-2 text-primary"></i>
                好友列表 <span id="online-count" class="ml-2 text-sm bg-primary/30 px-2 py-0.5 rounded-full">0</span>
            </h3>
        </div>

        <!-- 好友列表滚动容器 -->
        <div class="friends-scroll-container">
            <!-- 在线好友部分 -->
            <div class="section-header">在线好友</div>
            <div id="online-friends-container" class="p-2">
                <!-- 在线好友将通过JS动态生成 -->
                <div class="text-center text-gray-400 py-5">
                    <p>加载中...</p>
                </div>
            </div>

            <!-- 离线好友部分 -->
            <div class="section-header">离线好友</div>
            <div id="offline-friends-container" class="p-2">
                <!-- 离线好友将通过JS动态生成 -->
                <div class="text-center text-gray-400 py-5">
                    <p>加载中...</p>
                </div>
            </div>
        </div>

        <!-- 移动搜索框到好友列表底部 -->
        <div class="border-t border-gray-700 bg-gray-900/80 backdrop-blur-sm">
            <div class="section-header">添加好友</div>
            <div class="search-box">
                <!-- 优化后的两个输入框 -->
                <div class="split-input-container">
                    <input type="text" id="add-friend-username" class="split-input" placeholder="用户名" aria-label="用户名">
                    <span class="split-divider">#</span>
                    <input type="text" id="add-friend-id" class="split-input" placeholder="用户ID" aria-label="用户ID">
                </div>
                <button id="add-friend-button" class="search-button">
                    <i class="fa fa-paper-plane mr-2"></i> 发送好友请求
                </button>
                <div id="search-result" class="mt-2 text-sm hidden">
                    <!--搜索结果将在这里显示-->
                </div>
            </div>
        </div>
    </div>

    <!-- 导航栏 -->
    <nav class="bg-neutral/80 backdrop-blur-md shadow-lg sticky top-0 z-50 relative">
        <div class="container mx-auto px-4 py-3 flex justify-center items-center">
            <div class="text-2xl font-bold text-primary flex items-center">
                <i class="fa fa-gamepad mr-2"></i>
                <span>网络五子棋对战游戏</span>
            </div>
        </div>

        <!-- 新增：绝对定位的关机按钮 -->
        <button id="shutdown-btn" class="absolute right-4 top-1/2 transform -translate-y-1/2 shutdown-button">
            <i class="fa fa-power-off mr-1"></i> 退出
        </button>
    </nav>

    <!-- 主要内容区 -->
    <main class="container mx-auto px-4 py-8 max-w-5xl">
        <!-- 页面标题 -->
        <div class="text-center mb-10">
            <h1 class="text-[clamp(1.8rem,5vw,3rem)] font-bold mb-2">游戏大厅</h1>
            <p class="text-gray-400 text-lg">欢迎回来，<span id="username-display" class="text-primary"></span></p>
        </div>

        <!-- 用户信息卡片 -->
        <div class="max-w-3xl mx-auto mb-12">
            <div id="user-info-card" class="rank-card bg-neutral/50 border border-gray-700">
                <div class="flex flex-col md:flex-row items-center justify-between">
                    <!-- 用户基本信息 -->
                    <div class="flex flex-col md:flex-row items-center mb-6 md:mb-0">
                        <div class="mb-4 md:mb-0 mr-0 md:mr-6 flex-shrink-0">
                            <div id="avatar-container"
                                class="w-20 h-20 rounded-full bg-neutral flex items-center justify-center border-4 relative">
                                <i class="fa fa-user text-4xl text-gray-400"></i>
                                <span class="status-dot bg-green-500"></span>
                            </div>
                        </div>
                        <div class="text-center md:text-left">
                            <!-- 用户名后面会通过JS动态添加#ID -->
                            <h2 id="display-name" class="text-2xl font-bold mb-1"></h2>
                            <div class="flex items-center justify-center md:justify-start mb-2">
                                <span id="win-rate" class="text-gray-300">胜率: 68%</span>
                            </div>
                            <div id="rank-display"
                                class="flex items-center justify-center md:justify-start text-xl font-semibold">
                                <i class="fa fa-diamond mr-2 text-gold"></i>
                                <span>黄金 III 25胜点</span>
                            </div>
                        </div>
                    </div>
                    <!-- 统计信息 -->
                    <div id="stats-container" class="stats-grid w-full md:w-auto mt-4 md:mt-0">
                        <div class="stat-card">
                            <div class="text-gray-400 text-sm mb-1">总对局</div>
                            <div id="total-games" class="text-xl font-bold">128</div>
                        </div>
                        <div class="stat-card">
                            <div class="text-gray-400 text-sm mb-1">胜场</div>
                            <div id="win-games" class="text-xl font-bold text-green-500">87</div>
                        </div>
                        <div class="stat-card">
                            <div class="text-gray-400 text-sm mb-1">段位积分</div>
                            <div id="rank-points" class="text-xl font-bold">1250</div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 未参加排位赛提示 -->
            <div id="unranked-message" class="hidden">
                <div class="bg-neutral/50 rounded-xl p-6 text-center">
                    <div class="text-4xl mb-4"><i class="fa fa-meh-o text-gray-400"></i></div>
                    <h3 class="text-xl font-bold mb-2">还没参加排位赛</h3>
                    <p class="text-gray-400 mb-4">点击下方按钮开始你的第一场排位赛，展现你的实力！</p>
                    <div class="text-sm text-gray-500">完成1场排位赛后，将获得初始段位</div>
                </div>
            </div>
        </div>

        <!-- 匹配区域 -->
        <div class="max-w-lg mx-auto text-center">
            <div class="mb-8">
                <h2 class="text-2xl font-bold mb-4">寻找对手</h2>
                <p class="text-gray-400 mb-6">点击下方按钮开始匹配对手，我们将为您寻找实力相当的玩家</p>

                <button id="match-button" class="match-btn">
                    <i class="fa fa-search mr-2"></i>开始匹配
                </button>

                <div id="matching-status" class="mt-6 hidden">
                    <div class="inline-block p-4 rounded-full bg-neutral/50">
                        <div
                            class="w-16 h-16 border-4 border-primary border-t-transparent rounded-full animate-spin mx-auto mb-4">
                        </div>
                        <p class="text-lg">正在寻找对手中...</p>
                        <p class="text-gray-400 text-sm mt-1">匹配队列中: <span id="matching-time">0</span> 秒</p>
                    </div>
                </div>
            </div>

            <!-- 段位说明 -->
            <div id="rank-guide" class="bg-neutral/30 rounded-xl p-6 mb-8">
                <h3 class="text-xl font-bold mb-4 flex items-center">
                    <i class="fa fa-info-circle mr-2 text-primary"></i>段位说明
                </h3>
                <div class="grid grid-cols-3 md:grid-cols-4 gap-4">
                    <div class="text-center">
                        <div class="text-iron mb-1"><i class="fa fa-circle"></i></div>
                        <div class="text-sm">黑铁</div>
                    </div>
                    <div class="text-center">
                        <div class="text-bronze mb-1"><i class="fa fa-circle"></i></div>
                        <div class="text-sm">青铜</div>
                    </div>
                    <div class="text-center">
                        <div class="text-silver mb-1"><i class="fa fa-circle"></i></div>
                        <div class="text-sm">白银</div>
                    </div>
                    <div class="text-center">
                        <div class="text-gold mb-1"><i class="fa fa-diamond"></i></div>
                        <div class="text-sm">黄金</div>
                    </div>
                    <div class="text-center">
                        <div class="text-platinum mb-1"><i class="fa fa-star"></i></div>
                        <div class="text-sm">铂金</div>
                    </div>
                    <div class="text-center">
                        <div class="text-diamond mb-1"><i class="fa fa-certificate"></i></div>
                        <div class="text-sm">钻石</div>
                    </div>
                    <div class="text-center">
                        <div class="text-超凡 mb-1"><i class="fa fa-trophy"></i></div>
                        <div class="text-sm">超凡</div>
                    </div>
                    <div class="text-center">
                        <div class="text-神话 mb-1"><i class="fa fa-diamond"></i></div>
                        <div class="text-sm">神话</div>
                    </div>
                    <div class="text-center col-span-3 md:col-span-1">
                        <div class="text-赋能 mb-1"><i class="fa fa-rocket"></i></div>
                        <div class="text-sm">赋能</div>
                    </div>
                </div>
                <div class="mt-4 text-sm text-gray-400 text-center">
                    <p>每个段位分为 I-IV 四个小段位，I 为最高小段位</p>
                </div>
            </div>
        </div>
    </main>

    <!-- 页脚 -->
    <footer class="bg-neutral/80 backdrop-blur-md py-6 mt-12">
        <div class="container mx-auto px-4 text-center text-gray-400 text-sm">
            <p>© 2025 网络五子棋对战游戏 版权所有</p>
        </div>
    </footer>

    <script src="./js/jquery.min.js"></script>
    <script>
        // 段位映射表
        const ladderMap = {
            1: { name: '黑铁', color: 'iron', icon: 'fa-circle' },
            2: { name: '青铜', color: 'bronze', icon: 'fa-circle' },
            3: { name: '白银', color: 'silver', icon: 'fa-circle' },
            4: { name: '黄金', color: 'gold', icon: 'fa-diamond' },
            5: { name: '铂金', color: 'platinum', icon: 'fa-star' },
            6: { name: '钻石', color: 'diamond', icon: 'fa-certificate' },
            7: { name: '超凡', color: '超凡', icon: 'fa-trophy' },
            8: { name: '神话', color: '神话', icon: 'fa-diamond' },
            9: { name: '赋能', color: '赋能', icon: 'fa-rocket' }
        };

        // 小段位数字转罗马数字（反转映射）
        const rankToRoman = {
            1: 'IV',
            2: 'III',
            3: 'II',
            4: 'I'
        };

        // 按钮状态
        let buttonFlag = "stop";
        let wsHdl = null;
        let matchingTimer = null;
        let matchingSeconds = 0;
        let currentUserId = null; // 当前用户ID，用于排除自己
        let currentUsername = null; // 当前用户名
        let heartbeat_interval = 30000; // 心跳包30s发送一次
        let heartbeat_timer = 0;

        // 页面加载完成后执行
        document.addEventListener('DOMContentLoaded', function () {
            // 绑定匹配按钮点击事件
            const matchButton = document.getElementById('match-button');
            matchButton.addEventListener('click', handleMatchButtonClick);

            // 绑定添加好友按钮点击事件
            const addFriendButton = document.getElementById('add-friend-button');
            addFriendButton.addEventListener('click', handleAddFriend);

            // 绑定回车键添加好友
            const addFriendIdInput = document.getElementById('add-friend-id');
            addFriendIdInput.addEventListener('keyup', function (event) {
                if (event.key === 'Enter') {
                    handleAddFriend();
                }
            });

            // 用户名输入框Tab键自动跳到ID输入框
            const addFriendUsernameInput = document.getElementById('add-friend-username');
            addFriendUsernameInput.addEventListener('keydown', function (event) {
                if (event.key === 'Tab') {
                    event.preventDefault();
                    document.getElementById('add-friend-id').focus();
                }
            });

            // 绑定关机按钮点击事件
            const shutdownBtn = document.getElementById('shutdown-btn');
            shutdownBtn.addEventListener('click', handleShutdown);
        });

        // 获取并显示用户信息
        function getUserInfo() {
            $.ajax({
                url: "/info",
                type: "get",
                success: function (res) {
                    // 保存当前用户ID
                    currentUserId = res.id;
                    currentUsername = res.username;

                    // 计算胜率
                    const winRate = res.total_count > 0 ? Math.round((res.win_count / res.total_count) * 100) : 0;

                    const username = res.username || '玩家';
                    const userDisplay = `${username}#${res.id}`; // 关键：用户名+#ID格式
                    document.getElementById('username-display').textContent = userDisplay;
                    document.getElementById('display-name').textContent = userDisplay; // 这里会在用户信息卡片显示带ID的用户名

                    // 处理未参加排位赛的情况
                    if (res.ladder === 0) {
                        document.getElementById('user-info-card').classList.add('hidden');
                        document.getElementById('unranked-message').classList.remove('hidden');
                    } else {
                        // 正常显示段位信息
                        document.getElementById('user-info-card').classList.remove('hidden');
                        document.getElementById('unranked-message').classList.add('hidden');

                        // 获取段位信息
                        const ladderInfo = ladderMap[res.ladder] || ladderMap[1];
                        const romanRank = rankToRoman[res.rank] || 'I';

                        // 更新页面元素
                        document.getElementById('win-rate').textContent = `胜率: ${winRate}%`;
                        document.getElementById('total-games').textContent = res.total_count;
                        document.getElementById('win-games').textContent = res.win_count;
                        document.getElementById('rank-points').textContent = res.score;

                        // 更新段位显示
                        const rankDisplay = document.getElementById('rank-display');
                        rankDisplay.innerHTML = `<i class="fa ${ladderInfo.icon} mr-2 text-${ladderInfo.color}"></i><span>${ladderInfo.name} ${romanRank} ${res.score}胜点</span>`;

                        // 设置段位徽章颜色
                        document.querySelector('.w-20.h-20.rounded-full.border-4').className += ` border-${ladderInfo.color}`;
                    }

                    // 确保段位说明始终显示
                    document.getElementById('rank-guide').classList.remove('hidden');

                    // 初始化WebSocket连接
                    initWebSocket();
                },
                error: function (xhr) {
                    alert(JSON.stringify(xhr));
                    location.replace("/login.html");
                }
            });
        }

        // 初始化WebSocket连接
        function initWebSocket() {
            try {
                const wsUrl = "ws://" + location.host + "/hall";
                wsHdl = new WebSocket(wsUrl);

                wsHdl.onopen = function () {
                    console.log("WebSocket连接已建立");
                    // 连接成功后请求好友列表
                    requestFriendList();
                    // 开始心跳
                    startHeartBeat();
                };

                wsHdl.onmessage = function (evt) {
                    console.log(evt.data);
                    const rspJson = JSON.parse(evt.data);

                    if (rspJson.result === false) {
                        alert(evt.data);
                        location.replace("/login.html");
                        return;
                    }

                    if (rspJson["optype"] == "hall_ready") {
                        console.log("游戏大厅连接建立成功！");
                    } else if (rspJson["optype"] == "match_success") {
                        // 对战匹配成功，清除计时器
                        stopMatchingTimer();
                        alert("对战匹配成功，进入游戏房间！");
                        location.replace("/game_room.html");
                    } else if (rspJson["optype"] == "match_start") {
                        console.log("玩家已经加入匹配队列");
                        buttonFlag = "start";
                        updateMatchButton();
                        document.getElementById('matching-status').classList.remove('hidden');
                        //开始计时
                        startMatchingTimer();
                    } else if (rspJson["optype"] == "match_stop") {
                        console.log("玩家已经移除匹配队列");
                        buttonFlag = "stop";
                        updateMatchButton();
                        document.getElementById('matching-status').classList.add('hidden');
                        // 停止计时
                        stopMatchingTimer();
                    } else if (rspJson["optype"] == "get_friend_list") {
                        // 接收好友列表
                        renderFriendList(rspJson.data);
                    } else if (rspJson["optype"] == "friend_status_change") {
                        // 好友状态变化
                        updateFriendStatus(rspJson.data);
                    } else if (rspJson["optype"] == "send_challenge") {
                        challenge(rspJson);
                    } else if (rspJson["optype"] == "challenge_response") {
                        // 处理对战邀请响应
                        handleInviteResponse(rspJson);
                    } else if (rspJson["optype"] == "add_friend") {
                        // 处理添加好友结果
                        console.log("开始处理好友请求");
                        handleAddFriendResult(rspJson);
                    } else if (rspJson["optype"] == "add_friend_yes") {
                        alert("添加好友成功");
                    } else if (rspJson["optype"] == "add_friend_no") {
                        alert(rspJson.reason);
                    } else if (rspJson["optype"] == "logout") {
                        console.log("登出");
                    } else if (rspJson["optype"] == "heartbeat_ack") {
                        // 心跳成功
                        console.log("收到心跳检测");
                    }
                    else {
                        alert("未知请求类型");
                        console.log("收到未知消息:", rspJson);
                    }
                };

                wsHdl.onclose = function () {
                    console.log("WebSocket连接已关闭");
                    // 暂停心跳
                    stopHeartBeat();
                    //// 显示连接关闭提示
                    //document.getElementById('online-friends-container').innerHTML = `
                    //    <div class="text-center text-gray-400 py-5">
                    //        <p>连接已断开，正在重连...</p>
                    //    </div>
                    //`;
                    //document.getElementById('offline-friends-container').innerHTML = `
                    //    <div class="text-center text-gray-400 py-5">
                    //        <p>连接已断开，正在重连...</p>
                    //    </div>
                    //`;
                    //// 尝试重连
                    //setTimeout(initWebSocket, 3000);
                };

                wsHdl.onerror = function (error) {
                    console.error("WebSocket错误:", error);
                    alert("连接服务器失败，请稍后再试");
                };
            } catch (e) {
                console.error("创建WebSocket连接失败:", e);
                alert("连接服务器失败，请稍后再试");
            }
        }

        function sendHeartBeat() {
            // 发送心跳包
            if (wsHdl && wsHdl.readyState === WebSocket.OPEN) {
                const reqJson = {
                    optype: "heartbeat",
                    id: currentUserId
                };
                wsHdl.send(JSON.stringify(reqJson));
                console.log("发送心跳包");
                console.log(JSON.stringify(reqJson));
            }
        }

        function startHeartBeat() {
            // 开始心跳
            clearInterval(heartbeat_timer); // 先清除旧的定时器，避免重复
            heartbeat_timer = setInterval(sendHeartBeat, heartbeat_interval);// 设置定时器，每30秒发送心跳包
        }

        function stopHeartBeat() {
            // 停止心跳
            clearInterval(heartbeat_timer); // 清除定时器
        }


        // 请求好友列表
        function requestFriendList() {
            if (wsHdl && wsHdl.readyState === WebSocket.OPEN) {
                const reqJson = {
                    optype: "get_friend_list"
                };
                wsHdl.send(JSON.stringify(reqJson));
            }
        }

        // 渲染好友列表
        function renderFriendList(friends) {
            const onlineFriends = friends.filter(friend => friend.status === '在线');
            const gameFriends = friends.filter(friend => friend.status === '游戏中');
            const offlineFriends = friends.filter(friend => friend.status === '离线');

            // 更新在线用户数量
            document.getElementById('online-count').textContent = `${onlineFriends.length + gameFriends.length}/${friends.length}`;

            // 渲染在线好友
            const onlineContainer = document.getElementById('online-friends-container');
            if (onlineFriends.length === 0 && gameFriends.length === 0) {
                onlineContainer.innerHTML = `
            <div class="text-center text-gray-400 py-5">
                <p>没有在线或游戏中的好友</p>
            </div>
        `;
            } else {
                let html = '';
                const allOnlineAndGameFriends = [...onlineFriends, ...gameFriends];
                allOnlineAndGameFriends.forEach(friend => {
                    let rankInfoHtml = '';

                    // 处理段位信息
                    if (friend.ladder === 0) {
                        rankInfoHtml = `<span class="text-xs text-gray-400">未参加定位赛</span>`;
                    } else {
                        const ladderInfo = ladderMap[friend.ladder] || ladderMap[1];
                        const romanRank = rankToRoman[friend.rank] || 'I';
                        rankInfoHtml = `<span class="text-xs text-gray-400">${ladderInfo.name} ${romanRank} ${friend.score}胜点</span>`;
                    }

                    let statusText = '在线';
                    let statusDotClass = 'bg-green-500';
                    let inviteBtnDisabled = false;
                    if (friend.status === '游戏中') {
                        statusText = '游戏中';
                        statusDotClass = 'bg-yellow-500';
                        inviteBtnDisabled = true;
                    }

                    html += `
                <div class="user-item" data-id="${friend.id}">
                    <div class="user-avatar">
                        <i class="fa fa-user text-xl text-gray-400"></i>
                        <span class="status-dot ${statusDotClass}"></span>
                    </div>
                    <div class="flex-1 min-w-0">
                        <div class="flex items-center justify-between">
                            <h4 class="font-medium text-sm truncate">${friend.username}#${friend.id}</h4>
                            <span class="text-xs text-gray-400">${statusText}</span>
                        </div>
                        <div class="flex items-center justify-between">
                            ${rankInfoHtml}
                            <button class="invite-btn ml-2 text-primary text-sm ${inviteBtnDisabled ? 'opacity-50 cursor-not-allowed' : 'opacity-75 hover:opacity-100 transition-opacity'}"
                                    ${inviteBtnDisabled ? 'disabled' : `onclick="sendChallenge(${friend.id}, '${friend.username}')"`}>
                                <i class="fa fa-gamepad"></i> 邀请
                            </button>
                        </div>
                    </div>
                </div>
            `;
                });
                onlineContainer.innerHTML = html;
            }

            // 渲染离线好友
            const offlineContainer = document.getElementById('offline-friends-container');
            if (offlineFriends.length === 0) {
                offlineContainer.innerHTML = `
            <div class="text-center text-gray-400 py-5">
                <p>没有离线的好友</p>
            </div>
        `;
            } else {
                let html = '';
                offlineFriends.forEach(friend => {
                    let rankInfoHtml = '';

                    // 处理段位信息
                    if (friend.ladder === 0) {
                        rankInfoHtml = `<span class="text-xs text-gray-400">未参加定位赛</span>`;
                    } else {
                        const ladderInfo = ladderMap[friend.ladder] || ladderMap[1];
                        const romanRank = rankToRoman[friend.rank] || 'I';
                        rankInfoHtml = `<span class="text-xs text-gray-400">${ladderInfo.name} ${romanRank} ${friend.score}胜点</span>`;
                    }

                    html += `
                <div class="user-item" data-id="${friend.id}">
                    <div class="user-avatar">
                        <i class="fa fa-user text-xl text-gray-400"></i>
                        <span class="status-dot bg-gray-500"></span>
                    </div>
                    <div class="flex-1 min-w-0">
                        <div class="flex items-center justify-between">
                            <h4 class="font-medium text-sm truncate">${friend.username}#${friend.id}</h4>
                            <span class="text-xs text-gray-400">离线</span>
                        </div>
                        <div class="flex items-center justify-between">
                            ${rankInfoHtml}
                            <button class="invite-btn ml-2 text-primary text-sm opacity-50 cursor-not-allowed" disabled>
                                <i class="fa fa-gamepad"></i> 邀请
                            </button>
                        </div>
                    </div>
                </div>
            `;
                });
                offlineContainer.innerHTML = html;
            }
        }

        // 更新好友状态
        function updateFriendStatus(friend) {
            // 重新请求好友列表并刷新显示
            requestFriendList();
        }

        // 发送对战邀请
        function sendChallenge(userId, username) {
            if (!wsHdl || wsHdl.readyState !== WebSocket.OPEN) {
                alert("与服务器的连接已断开，请刷新页面重试");
                return;
            }

            if (buttonFlag === "start") {
                alert("您正在匹配队列中，无法发送邀请");
                return;
            }

            const confirmSend = confirm(`确定要向 ${username} 发送对战邀请吗？`);
            if (confirmSend) {
                const reqJson = {
                    optype: "send_challenge",
                    dst_id: userId,
                    src_id: currentUserId,
                    src_username: currentUsername
                };
                console.log(JSON.stringify(reqJson));
                wsHdl.send(JSON.stringify(reqJson));
            }
        }

        // 收到对战邀请
        function challenge(data) {
            const who = data.src_username;
            console.log(data);
            if (confirm(`${who} 想邀请你进行对战，是否接受？`)) {
                // 用户点击"确定"，接受
                const reqJson = {
                    optype: "challenge_response",
                    dst_id: data.dst_id,
                    src_id: data.src_id,
                    src_username: data.src_username,
                    ans: true
                };
                alert("您接受了对方的对战邀请，进入游戏房间！");
                wsHdl.send(JSON.stringify(reqJson));
                location.replace("/game_room.html");

            } else {
                // 用户点击"取消"，拒绝
                const reqJson = {
                    optype: "challenge_response",
                    dst_id: data.dst_id,
                    src_id: data.src_id,
                    src_username: data.src_username,
                    ans: false
                };
                wsHdl.send(JSON.stringify(reqJson));
            }
        }

        // 处理对战邀请响应
        function handleInviteResponse(data) {
            if (data.ans) {
                // 对方接受邀请，进入游戏房间
                alert("对方接受了您的对战邀请，进入游戏房间！");
                location.replace("/game_room.html");
            } else {
                // 对方拒绝邀请
                alert("对方拒绝了您的对战邀请");
            }
        }

        // 处理匹配按钮点击
        function handleMatchButtonClick() {
            if (!wsHdl || wsHdl.readyState !== WebSocket.OPEN) {
                alert("与服务器的连接已断开，请刷新页面重试");
                return;
            }

            if (buttonFlag == "stop") {
                // 开始匹配
                const reqJson = {
                    optype: "match_start"
                };
                wsHdl.send(JSON.stringify(reqJson));
            } else {
                // 停止匹配
                const reqJson = {
                    optype: "match_stop"
                };
                wsHdl.send(JSON.stringify(reqJson));
            }
        }

        // 开始匹配计时器
        function startMatchingTimer() {
            // 重置计时
            matchingSeconds = 0;
            document.getElementById('matching-time').textContent = matchingSeconds;

            // 启动计时器，每秒更新一次
            matchingTimer = setInterval(function () {
                matchingSeconds++;
                document.getElementById('matching-time').textContent = matchingSeconds;
            }, 1000);
        }

        // 停止匹配计时器
        function stopMatchingTimer() {
            if (matchingTimer) {
                clearInterval(matchingTimer);
                matchingTimer = null;
                matchingSeconds = 0;
                document.getElementById('matching-time').textContent = matchingSeconds;
            }
        }

        // 更新匹配按钮状态
        function updateMatchButton() {
            const matchButton = document.getElementById('match-button');

            if (buttonFlag == "start") {
                matchButton.innerHTML = '<i class="fa fa-spinner fa-spin mr-2"></i>匹配中...点击停止';
                matchButton.className = 'matching-btn';
            } else {
                matchButton.innerHTML = '<i class="fa fa-search mr-2"></i>开始匹配';
                matchButton.className = 'match-btn';
            }
        }

        // 处理添加好友
        function handleAddFriend() {
            // 获取输入框的内容，value表示获取内容，trim表示去除收尾的空格
            const username = document.getElementById('add-friend-username').value.trim();
            const userId = document.getElementById('add-friend-id').value.trim();

            if (!username || !userId) {
                alert('请输入用户名和ID');
                return;
            }

            if (isNaN(userId)) {
                alert('用户ID必须是数字');
                return;
            }

            const reqJson = {
                optype: "add_friend",
                dst_username: username,
                dst_id: userId,
                src_username: currentUsername,
                src_id: currentUserId
            };
            wsHdl.send(JSON.stringify(reqJson));
            alert('好友请求发送成功');
            //alert(JSON.stringify(reqJson));

            // 清空输入框
            document.getElementById('add-friend-username').value = '';
            document.getElementById('add-friend-id').value = '';
        }

        // 收到添加好友的请求
        function handleAddFriendResult(resp) {
            //const {who} = resp;
            const who = resp.src_username;
            const id = resp.src_id;
            console.log(resp);
            if (confirm(`${who} 想添加你为好友，是否接受？`)) {
                // 用户点击"确定"，接受好友请求
                acceptFriendRequest(resp);
            } else {
                // 用户点击"取消"，拒绝好友请求
                rejectFriendRequest(resp);
            }
        }

        function acceptFriendRequest(resp) {
            // 确认添加，则发送add_friend_yes，由后端在数据库中建立好友关系
            const reqJson = {
                optype: "add_friend_yes",
                dst_username: resp.dst_username,
                dst_id: resp.dst_id,
                src_username: resp.src_username,
                src_id: resp.src_id
            }
            wsHdl.send(JSON.stringify(reqJson));
            console.log(JSON.stringify(reqJson));
        }
        function rejectFriendRequest(resp) {
            const reqJson = {
                optype: "add_friend_no",
                dst_username: resp.dst_username,
                dst_id: resp.dst_id,
                src_username: resp.src_username,
                src_id: resp.src_id
            }
            wsHdl.send(JSON.stringify(reqJson));
        }

        // 关机按钮处理函数
        function handleShutdown() {
            if (confirm('确定要退出游戏大厅吗？')) {
                // 1. 向服务器发送离线状态通知
                if (wsHdl && wsHdl.readyState === WebSocket.OPEN) {
                    const offlineMsg = {
                        optype: "logout",
                        user_id: currentUserId,
                        username: currentUsername
                    };
                    // 同步发送离线消息（确保发送完成后再关闭连接）
                    wsHdl.send(JSON.stringify(offlineMsg));
                    // 短暂延迟确保消息发送成功
                    setTimeout(() => {
                        wsHdl.close();
                    }, 2000);
                }

                // 2. 关闭当前页面
                if (window.opener) {
                    // 如果是通过window.open打开的页面，直接关闭
                    window.close();
                } else {
                    // 普通页面提示手动关闭（部分浏览器限制window.close()）
                    //alert('已为您切换至离线状态，请手动关闭本页面');
                    // 可选：跳转到登录页
                    alert('您已退出登录，将为你跳转到首页, 您也可以直接关闭该窗口');
                    location.replace("/");
                }
            }
        }

        // 页面卸载前关闭WebSocket连接
        window.onbeforeunload = function () {
            if (wsHdl) {
                // 页面卸载前，向后端发送logout信号
                const offlineMsg = {
                    optype: "logout",
                    user_id: currentUserId,
                    username: currentUsername
                };
                // 同步发送离线消息（确保发送完成后再关闭连接）
                wsHdl.send(JSON.stringify(offlineMsg));
                // 短暂延迟确保消息发送成功
                setTimeout(() => {
                    wsHdl.close();
                }, 2000);
                wsHdl.close();
            }
            stopMatchingTimer();
        };
        getUserInfo();
    </script>
</body>

</html>